<template>
  <client-only>
    <el-dialog v-model="visible" :title="currFormOpt.title" :width="currFormOpt.width">
      <el-form :model="currForm" :label-width="currFormOpt.labelWidth" :rules="rule">
        <el-form-item v-for="item in currFormOpt.fieldList"
                      :key="item.fieldName"
                      :label="item.verboseName">

          <!-- 普通输入框 -->
          <el-input  v-model="currForm[item.fieldName]" v-if="item.fieldType === FormFieldType.input" :disabled="item.readonly"/>

          <!-- 密码输入框 -->
          <el-input  v-model="currForm[item.fieldName]" type="password" v-if="item.fieldType === FormFieldType.password" :disabled="item.readonly"/>

          <!-- 文本框 -->
          <el-input  v-model="currForm[item.fieldName]" type="textarea" v-if="item.fieldType === FormFieldType.textarea" :disabled="item.readonly"/>

          <!-- 数字录入框 -->
          <el-input  v-model="currForm[item.fieldName]" type="number" v-if="item.fieldType === FormFieldType.number" :disabled="item.readonly"/>

          <!-- select选择框 -->
          <el-select v-model="currForm[item.fieldName]"
                     :placeholder="`选择${item.verboseName}`"
                     :multiple="item.isMultiSelect"
                     :disabled="item.readonly"
                     v-if="item.fieldType === FormFieldType.select"
          >
            <el-option v-for="choice in item.selectSource"
                       :Key="choice.value"
                       :label="choice.text"
                       :value="choice.value" />
          </el-select>

          <!-- 级连选择框 -->
          <el-cascader v-model="currForm[item.fieldName]"
                       :options="item.selectSource"
                       :props="{checkStrictly: true, multiple: item.isMultiSelect, label: 'text'}"
                       :placeholder="`选择${item.verboseName}`"
                       @change="(val)=>{handleCascaderSelectChange(val, item)}"
                       :disabled="item.readonly"
                       clearable v-if="item.fieldType === FormFieldType.cascader"/>

          <!-- 开关 -->
          <el-switch v-model="currForm[item.fieldName]"
                     :active-text="item.selectSource[0].text"
                     :active-value="item.selectSource[0].value"
                     :inactive-text="item.selectSource[1].text"
                     :inactive-value="item.selectSource[1].value"
                     :disabled="item.readonly"
                     v-if="item.fieldType === FormFieldType.switch"
          />

          <!-- 日期选择器 -->
          <el-date-picker v-model="currForm[item.fieldName]"
                          type="date"
                          placeholder="选择对应日期"
                          :disabled="item.readonly"
                          v-if="item.fieldType === FormFieldType.date"
          />

          <!-- 文件上传 -->
          <el-upload
              v-model:file-list="fileList[item.fieldName]"
              class="upload-demo"
              :ref="refList[item.fieldName]"
              :action="item.uploadAction"
              :before-upload="(rawFile)=>{handleBeforeUpload(rawFile, item.uploadFormats, `${item.fieldName}UploadRef`)}"
              :on-success="(res)=>{handleUploadSuccess(res, item.fieldName)}"
              v-if="item.fieldType === FormFieldType.upload">
            <el-button type="primary">点击按钮上传</el-button>
            <template #tip>
              <div class="el-upload__tip">
                格式支持：{{ item.uploadFormats }}
              </div>
            </template>
          </el-upload>
        </el-form-item>
        <div class="form-btn">
          <el-button type="primary" @click="handleFormSubmit">确认</el-button>
          <el-button @click="handleCancel">取消</el-button>
        </div>
      </el-form>
    </el-dialog>
  </client-only>
</template>

<script setup lang="ts">

import {ref} from "vue";
import {UploadRawFile} from "element-plus";
import {FormFieldSetting, FormFieldType, FormOption} from "~/models/data/form";

const props = defineProps<{
  form: object,
  formOption: FormOption,
  rule: object,
  reload: Function,
}>();

/**
 * 初始化ref列表
 * **/
const initRefList = ()=>{
  let rls : any = {};
  props.formOption.fieldList.forEach(item=>{
    rls[item.fieldName] = ref(null);
  })
  return rls;
}

/**
 * 初始化文件列表
 * **/
const initFileList = ()=>{
  let fls : any = {};
  props.formOption.fieldList.forEach(item=>{
    fls[item.fieldName] = [];
  })
  return fls;
}

const visible = ref(false);
const currForm = ref<any>({});
const refList = ref(initRefList());
const fileList = ref(initFileList());
const currFormOpt = ref(props.formOption);

/**
 * 关闭弹出表单
 * **/
const close = ()=>{
  visible.value = false;
  currForm.value = {};
}

/**
 * 打开表单
 * **/
const open = (data? : any)=>{
  enableAllTreeSelect();
  if(data){
    currForm.value = data
    disableSelfInCascader(data);
  }else{
    currForm.value = {}
  }
  visible.value = true;
}

/**
 * 提交表单
 * **/
const handleFormSubmit = ()=>{
  // 提交数据
  currFormOpt.value.submitFunc(currForm.value);
}

/**
 * 取消提交表单
 * **/
const handleCancel = ()=>{
  close();
}

/**
 * 文件上传前的操作
 * **/
const handleBeforeUpload = (rawFile : UploadRawFile, uploadFormats : Array<string>, refName : string)=>{
  if(uploadFormats?.length??0 > 0){
    let fileNameSplit =  rawFile.name.split('.');
    if(fileNameSplit.length > 0)
    {
      let fileExt = fileNameSplit[fileNameSplit.length-1];
      if(uploadFormats.indexOf(fileExt.toLowerCase()) < 0){
        ElMessage.error("文件上传失败，请选择合法的文件格式");
        refList.value[refName].value.abort();
      }else{
        return;
      }
    }
  }else{
    return;
  }
}

/**
 * 文件下载接口
 * **/
const handleUploadSuccess = (res:any, columnName: string)=>{
  if(res.data){
    currForm.value[columnName] = res.data;
  }else{
    ElMessage.error();
  }
}

/**
 * cascader 发生变化时候的处理
 * **/
const handleCascaderSelectChange = (val: any, col: FormFieldSetting)=>{
  if(!col.isMultiSelect){
    currForm.value[col.fieldName] = val[val.length - 1];
  }
}

/**
 * 配置cascader选项在循环引用的表单中不要选中自己
 * **/
const disableSelfInCascader = (val : any)=>{
  currFormOpt.value.fieldList.forEach((item)=>{
    if(item.fieldType == FormFieldType.cascader){
      if(item.needHideSelf){
        item.selectSource?.forEach((node : any)=>{
          disableTreeBranch(val, node);
        })
      }
    }
  })
}

const disableTreeBranch = (val : any, node : any) => {
  let children = node['children'] as Array<any>;
  if(node['id'] === val['id']) {
    node['disabled'] = true;
    if(children?.length > 0){
      children.forEach(item=>{
        disableTreeBranch(item, item);
      })
    }
  }else{
    if(children?.length > 0){
      children.forEach(item=>{
        disableTreeBranch(val, item);
      })
    }
  }

}

/**
 * 开启所有 tree 选项
 * **/
const enableAllTreeSelect = ()=>{
  currFormOpt.value.fieldList.forEach((item)=>{
    if(item.fieldType == FormFieldType.cascader){
      if(item.needHideSelf){
        item.selectSource?.forEach((node : any)=>{
          enableTreeBranch(node);
        })
      }
    }
  })
}

/**
 * 开启树分支
 * **/
const enableTreeBranch = (node: any)=>{
  node['disabled'] = false;
  if(node['children']?.length > 0){
    (node['children'] as Array<any>).forEach(item=>{
      enableTreeBranch(item);
    })
  }
}


defineExpose({open, close});

</script>

<style scoped>
.form-btn {
  display: flex;
  padding: 0px;
  justify-content: flex-end;
  align-items: flex-end;
}
</style>